﻿using Microsoft.EntityFrameworkCore;
using NetByDocker.Domain;
using NetByDocker.Domain.Entities;
using NetByDocker.Domain.Model.Enum;
using StackExchange.Profiling;

namespace NetByDocker.Extensions;

public static class ApplicationBuilderExtensions
{
    /// <summary>
    /// 初始化数据
    /// </summary>
    public static async Task InitDataAsync(this IApplicationBuilder app)
    {
        using var scope = app.ApplicationServices.CreateScope();
        var services = scope.ServiceProvider;
        var loggerFactory = services.GetRequiredService<ILoggerFactory>();
        try
        {
            using (MiniProfiler.Current.Step("初始化数据库数据"))
            {
                var dbContext = services.GetRequiredService<DbContext>();
                await SeedAsync(dbContext, loggerFactory);
            }
        }
        catch (Exception ex)
        {
            var logger = loggerFactory.CreateLogger<Program>();
            logger.LogError(ex, "An error occurred seeding the DB.");
        }
    }

    /// <summary>
    /// 生成数据库以及数据种子
    /// </summary>
    /// <param name="context"></param>
    /// <param name="loggerFactory">日志</param>
    /// <param name="retry">重试次数</param>
    /// <returns></returns>
    private static async Task SeedAsync(DbContext context, ILoggerFactory loggerFactory, int? retry = 0)
    {
        var retryForAvailability = retry!.Value;
        try
        {
            //如果当前数据库不存在按照当前 model 创建，如果存在则将数据库调整到和当前 model 匹配
            await context.Database.MigrateAsync();

            if (!context.Set<User>().Any())
            {
                var grade1 = new Group("一班");
                await context.AddAsync(grade1).ConfigureAwait(false);
                var user1 = new User("admin1", "123456", "张三", SexEnum.Man, 10.12d,
                    grade1.Id);
                await context.AddAsync(user1).ConfigureAwait(false);
                var scoreList1 = new List<Score>
                                 {
                                     new Score("语文", 80, user1.Id), new Score("数学", 90, user1.Id), new Score("英语", 30, user1.Id)
                                 };
                await context.AddRangeAsync(scoreList1).ConfigureAwait(false);
                var user2 = new User("admin2", "123456", "李四", SexEnum.WoMan, 80.10d,
                    grade1.Id);
                await context.AddAsync(user2).ConfigureAwait(false);
                var scoreList2 = new List<Score>
                                 {
                                     new Score("语文", 70, user2.Id), new Score("数学", 60, user2.Id), new Score("英语", 10, user2.Id)
                                 };
                await context.AddRangeAsync(scoreList2).ConfigureAwait(false);

                var grade2 = new Group("二班");
                await context.AddAsync(grade2).ConfigureAwait(false);
                var user3 = new User("admin3", "123456", "王五", SexEnum.Man, 25.30d,
                    grade2.Id);
                await context.AddAsync(user3).ConfigureAwait(false);
                var scoreList3 = new List<Score> { new Score("语文", 50, user3.Id), new Score("数学", 40, user3.Id) };
                await context.AddRangeAsync(scoreList3).ConfigureAwait(false);

                var grade3 = new Group("三班");
                await context.AddAsync(grade3).ConfigureAwait(false);
                await context.SaveChangesAsync().ConfigureAwait(false);
            }
        }
        catch (Exception ex)
        {
            if (retryForAvailability < 3)
            {
                retryForAvailability++;
                var log = loggerFactory.CreateLogger<Program>();
                log.LogError($"迁移出错：{ex.Message}");
                await SeedAsync(context, loggerFactory, retryForAvailability).ConfigureAwait(false);
            }
        }
    }
}